#pragma once
#include <string>
#include <vector>
#include <tuple>
#include <limits>

#include "painter.hh"

namespace icesp
{
    struct painter;

    namespace graph
    {
        struct edge // XXX must be aligned and have no padding
        {
            // TODO weight_type generic?
            using weight_type = int;
            weight_type static constexpr weight_max_value =
                std::numeric_limits<edge::weight_type>::max();

            int from;
            int to;
            weight_type weight;
        };

        struct adj_matrix
        {
            // TODO
            /* using index_type = decltype(sizeof 0); // same as int according to the standard */
            adj_matrix(std::string const& filepath);
            void dump_to_obj(std::string const& filepath);
            void reset_result();
            void pad(int npad, int* colors);
            void realloc_result_pad();

            int n; // nodes number
            int m; // edges number
            std::vector<edge> edges;
            std::vector<int> edge_index;
            std::vector<int> index;  //  index for node in renumber
            std::vector<int> rindex; // rindex for node in renumber
            std::vector<edge::weight_type> result;

            // for pad
            int n_after_pad;
            int* tos;
            int* ws;
            int* pad_color;
            int* pad_old;
            int* new_node;
            int* new_node_map;

            friend void renumber(graph::adj_matrix& g, painter& p);

        private:
            void free_and_allocate_int_array(int* & p, int n);
            void build_index();
        };

        void renumber(graph::adj_matrix& g, painter& p);
    }
}

